import 'leaflet'
import { type VNode } from 'vue'
import { render } from 'vue'
import HeatMap from '../../Heatmap/index'
import { yesBtnSvg, loadingBtnSvg } from '../../const'

import * as L from 'leaflet'
const yx = L.latLng
export function xy(x: number, y: number): L.LatLng | L.LatLngTuple {
  return yx(y, x) // When doing xy(x, y);
}

//获取屏幕缩放比例
export function getRatio() {
  let ratio = 1
  // const screen = window.screen;
  const ua = navigator.userAgent.toLowerCase()

  if (window.devicePixelRatio !== undefined) {
    ratio = window.devicePixelRatio
  } else if (~ua.indexOf('msie')) {
    // if (screen.deviceXDPI && screen.logicalXDPI) {
    //   ratio = screen.deviceXDPI / screen.logicalXDPI;
    // }
  } else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
    ratio = window.outerWidth / window.innerWidth
  }

  // if (ratio) {
  //   ratio = Math.round(ratio * 100);
  // }
  return ratio
}

export function getCenterPoint(latLng1: L.LatLng, latLng2: L.LatLng) {
  let lng = latLng1.lng // 取平均值得到中心点的X坐标
  let lat = latLng1.lat // 取平均值得到中心点的Y坐标
  if (latLng1.lng > latLng2.lng) lng = latLng2.lng + (latLng1.lng - latLng2.lng) / 2
  if (latLng1.lng < latLng2.lng) lng = latLng1.lng + (latLng2.lng - latLng1.lng) / 2
  if (latLng1.lat > latLng2.lat) lat = latLng2.lat + (latLng1.lat - latLng2.lat) / 2
  if (latLng1.lat < latLng2.lat) lat = latLng1.lat + (latLng2.lat - latLng1.lat) / 2
  return xy(lng, lat)
}

// https://github.com/rowanwins/point-in-polygon-hao
// The input polygon format aligns with the GeoJson specification for polygons.
// This means that the first and last coordinate in a polygon must be repeated, if not this library will throw an error.
// This does not support multi-polygons.
// point [ 1.5, 1.5 ]， polygon  [[[1, 1],[1, 2],[2, 2],[2, 1],[1, 1]]];
export function pointInPolygon(p: number[], polygon: number[][][]) {
  let i = 0
  let ii = 0
  let k = 0
  let f = 0
  let u1 = 0
  let v1 = 0
  let u2 = 0
  let v2 = 0

  const x = p[0]
  const y = p[1]

  const numContours = polygon.length
  for (i; i < numContours; i++) {
    ii = 0
    const contourLen = polygon[i].length - 1
    const contour = polygon[i]

    let currentP = contour[0]
    if (currentP[0] !== contour[contourLen][0] && currentP[1] !== contour[contourLen][1]) {
      throw new Error('First and last coordinates in a ring must be the same')
    }

    u1 = currentP[0] - x
    v1 = currentP[1] - y

    for (ii; ii < contourLen; ii++) {
      const nextP = contour[ii + 1]

      v2 = nextP[1] - y

      if ((v1 < 0 && v2 < 0) || (v1 > 0 && v2 > 0)) {
        currentP = nextP
        v1 = v2
        u1 = currentP[0] - x
        continue
      }

      u2 = nextP[0] - p[0]

      if (v2 > 0 && v1 <= 0) {
        f = u1 * v2 - u2 * v1
        if (f > 0) k = k + 1
        else if (f === 0) return 0
      } else if (v1 > 0 && v2 <= 0) {
        f = u1 * v2 - u2 * v1
        if (f < 0) k = k + 1
        else if (f === 0) return 0
      } else if (v2 === 0 && v1 < 0) {
        f = u1 * v2 - u2 * v1
        if (f === 0) return 0
      } else if (v1 === 0 && v2 < 0) {
        f = u1 * v2 - u2 * v1
        if (f === 0) return 0
      } else if (v1 === 0 && v2 === 0) {
        if (u2 <= 0 && u1 >= 0) {
          return 0
        } else if (u1 <= 0 && u2 >= 0) {
          return 0
        }
      }
      currentP = nextP
      v1 = v2
      u1 = u2
    }
  }

  if (k % 2 === 0) return false
  return true
}

export function getDisance(p1: L.LatLng, p2: L.LatLng): number {
  let dx = Math.abs(p2.lng - p1.lng)
  let dy = Math.abs(p2.lat - p1.lat)
  let dis = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2))
  return dis
}


/**
     * create bitmap image
     * 按照规则生成图片响应头和响应体
     */
 export const genBitmapImage  = function (oData) {
  //
  // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
  // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
  //

  const biWidth = oData.width;
  const biHeight = oData.height;
  const biSizeImage = biWidth * biHeight * 3;
  const bfSize = biSizeImage + 54; // total header size = 54 bytes

  //
  //  typedef struct tagBITMAPFILEHEADER {
  //  	WORD bfType;
  //  	DWORD bfSize;
  //  	WORD bfReserved1;
  //  	WORD bfReserved2;
  //  	DWORD bfOffBits;
  //  } BITMAPFILEHEADER;
  //
  const BITMAPFILEHEADER = [
      // WORD bfType -- The file type signature; must be "BM"
      0x42,
      0x4d,
      // DWORD bfSize -- The size, in bytes, of the bitmap file
      bfSize & 0xff,
      (bfSize >> 8) & 0xff,
      (bfSize >> 16) & 0xff,
      (bfSize >> 24) & 0xff,
      // WORD bfReserved1 -- Reserved; must be zero
      0,
      0,
      // WORD bfReserved2 -- Reserved; must be zero
      0,
      0,
      // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
      54,
      0,
      0,
      0,
  ];

  //
  //  typedef struct tagBITMAPINFOHEADER {
  //  	DWORD biSize;
  //  	LONG  biWidth;
  //  	LONG  biHeight;
  //  	WORD  biPlanes;
  //  	WORD  biBitCount;
  //  	DWORD biCompression;
  //  	DWORD biSizeImage;
  //  	LONG  biXPelsPerMeter;
  //  	LONG  biYPelsPerMeter;
  //  	DWORD biClrUsed;
  //  	DWORD biClrImportant;
  //  } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
  //
  const BITMAPINFOHEADER = [
      // DWORD biSize -- The number of bytes required by the structure
      40,
      0,
      0,
      0,
      // LONG biWidth -- The width of the bitmap, in pixels
      biWidth & 0xff,
      (biWidth >> 8) & 0xff,
      (biWidth >> 16) & 0xff,
      (biWidth >> 24) & 0xff,
      // LONG biHeight -- The height of the bitmap, in pixels
      biHeight & 0xff,
      (biHeight >> 8) & 0xff,
      (biHeight >> 16) & 0xff,
      (biHeight >> 24) & 0xff,
      // WORD biPlanes -- The number of planes for the target device. This value must be set to 1
      1,
      0,
      // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
      // has a maximum of 2^24 colors (16777216, Truecolor)
      24,
      0,
      // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
      0,
      0,
      0,
      0,
      // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
      biSizeImage & 0xff,
      (biSizeImage >> 8) & 0xff,
      (biSizeImage >> 16) & 0xff,
      (biSizeImage >> 24) & 0xff,
      // LONG biXPelsPerMeter, unused
      0,
      0,
      0,
      0,
      // LONG biYPelsPerMeter, unused
      0,
      0,
      0,
      0,
      // DWORD biClrUsed, the number of color indexes of palette, unused
      0,
      0,
      0,
      0,
      // DWORD biClrImportant, unused
      0,
      0,
      0,
      0,
  ];

  const iPadding = (4 - ((biWidth * 3) % 4)) % 4;

  const aImgData = oData.data;

  let strPixelData = "";
  const biWidth4 = biWidth << 2;
  let y = biHeight;
  const fromCharCode = String.fromCharCode;

  do {
      const iOffsetY = biWidth4 * (y - 1);
      let strPixelRow = "";
      for (let x = 0; x < biWidth; x++) {
          const iOffsetX = x << 2;
          strPixelRow +=
              fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) +
              fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) +
              fromCharCode(aImgData[iOffsetY + iOffsetX]);
      }

      for (let c = 0; c < iPadding; c++) {
          strPixelRow += String.fromCharCode(0);
      }

      strPixelData += strPixelRow;
  } while (--y);

  return (
      encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) +
      encodeData(strPixelData)
  );
};

function encodeData(data) {
  if (!window.btoa) {
      // eslint-disable-next-line no-throw-literal
      throw "btoa undefined";
  }
  let str = "";
  if (typeof data == "string") {
      str = data;
  } else {
      for (let i = 0; i < data.length; i++) {
          str += String.fromCharCode(data[i]);
      }
  }

  return btoa(str);
}